package com.seanliao.nav.config;

import com.seanliao.nav.properties.SecurityProperties;
import com.seanliao.nav.security.MyAuthenticationFilter;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.security.config.annotation.authentication.configuration.AuthenticationConfiguration;
import org.springframework.security.config.annotation.method.configuration.EnableMethodSecurity;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
import org.springframework.security.config.annotation.web.configurers.AbstractHttpConfigurer;
import org.springframework.security.core.session.SessionRegistry;
import org.springframework.security.core.session.SessionRegistryImpl;
import org.springframework.security.web.SecurityFilterChain;
import org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter;
import org.springframework.web.cors.CorsConfiguration;
import org.springframework.web.cors.CorsConfigurationSource;
import org.springframework.web.cors.UrlBasedCorsConfigurationSource;


/**
 * spring security配置
 */
@Configuration
@EnableWebSecurity
@EnableMethodSecurity(securedEnabled = true)
public class SecurityConfig {

    @Autowired
    private SecurityProperties securityProperties;

    /**
     * 认证管理器
     */
    @Bean
    public AuthenticationManager authenticationManager(AuthenticationConfiguration authenticationConfiguration) throws Exception {
        return authenticationConfiguration.getAuthenticationManager();
    }

    /**
     * 跨域
     */
//    @Bean
    public CorsConfigurationSource corsConfigurationSource() {
        UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource();
        CorsConfiguration corsConfiguration = new CorsConfiguration();
        corsConfiguration.addAllowedHeader("*");
        securityProperties.getCorsWhite().forEach(corsConfiguration::addAllowedOrigin);
        corsConfiguration.addAllowedMethod("*");
        corsConfiguration.setAllowCredentials(true);
        source.registerCorsConfiguration("/**", corsConfiguration.applyPermitDefaultValues());
        return source;
    }

    /**
     * session管理器
     */
    @Bean
    public SessionRegistry sessionRegistry() {
        return new SessionRegistryImpl();
    }

    /**
     * 权限过滤链
     */
    @Bean
    public SecurityFilterChain securityFilterChain(HttpSecurity httpSecurity) throws Exception {
        return httpSecurity
                // 授权配置
                .authorizeHttpRequests(authorize -> {
                    String[] urlWhite = securityProperties.getUrlWhite().toArray(new String[0]);
                    // 白名单免登录
                    authorize.requestMatchers(urlWhite).permitAll();
                    // 其他需要登录
                    authorize.anyRequest().authenticated();
                })
                // 关闭自带的登录处理，这时无需重写UsernamePasswordAuthenticationFilter
                .formLogin(AbstractHttpConfigurer::disable)
                // 关闭自带的登出处理
                .logout(AbstractHttpConfigurer::disable)
                // 跨域
                .cors(cors -> cors.configurationSource(corsConfigurationSource()))
                // 关闭跨站请求伪造
                .csrf(AbstractHttpConfigurer::disable)
                // 加入自定义过滤器
                .addFilterBefore(new MyAuthenticationFilter(), UsernamePasswordAuthenticationFilter.class)
                // 会话配置
                .sessionManagement(sessionConfig -> sessionConfig.maximumSessions(1))
                // 构建
                .build();
    }

}
